//
//  CIMSignalService.m
//  CIMSDK
//
//  Created by Chentao on 2022/9/2.
//

#import "CIMSignalService.h"
#import "GCDAsyncSocket.h"
#import "CIMSignalServiceBuffer.h"
#import "KCLDataWriter.h"

@implementation CIMSignalServiceConfig

@end

@interface CIMSignalService ()<GCDAsyncSocketDelegate, CIMSignalServiceBufferDelegate>

@property (nonatomic, strong) CIMSignalServiceBuffer *signalBuffer;

@property (nonatomic, strong) GCDAsyncSocket *socket;

@end

@implementation CIMSignalService

- (instancetype)init {
    self = [super init];

    if (self) {
        self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_queue_create("SignalServiceQueue", NULL)];

        self.signalBuffer = [[CIMSignalServiceBuffer alloc] init];
        self.signalBuffer.delegate = self;
    }
    return self;
}

- (BOOL)isConnected {
    return self.socket.isConnected;
}

- (void)connect {
    if (self.delegate && [self.delegate respondsToSelector:@selector(signalServiceWillConnect:)]) {
        [self.delegate signalServiceWillConnect:self];
    }

    NSError *error;
    [self.socket connectToHost:self.serviceConfig.host onPort:self.serviceConfig.port withTimeout:15 error:&error];

    if (error) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(signalServiceWillConnect:error:)]) {
            [self.delegate signalServiceWillConnect:self error:error];
        }
    }
}

- (void)close {
    [self.socket disconnect];
}

- (void)sendSignalPacket:(CIMSignalPacket *)signalPacket {
    KCLDataWriter *dataWriter = [KCLDataWriter writerWithData:[[NSMutableData alloc] init]];

    [dataWriter writeByte:signalPacket.tag];
    [dataWriter writeUInt16:signalPacket.bodyLength];

    if (signalPacket) {
        [dataWriter writeBytes:signalPacket.packetBody];
    }

    [self.socket writeData:dataWriter.data withTimeout:30 tag:0];
}

#pragma mark - GCDAsyncSocketDelegate
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    [self.signalBuffer clear];
    
    [sock readDataWithTimeout:-1 tag:0];
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(signalServiceConnectSuccess:)]) {
        [self.delegate signalServiceConnectSuccess:self];
    }
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)error {
    if (self.delegate && [self.delegate respondsToSelector:@selector(signalServiceDidDisconnect:error:)]) {
        [self.delegate signalServiceDidDisconnect:self error:error];
    }
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
    [sock readDataWithTimeout:-1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    [self.signalBuffer appendData:data];

    [sock readDataWithTimeout:-1 tag:0];
}

#pragma mark - CIMSignalServiceBufferDelegate

- (void)signalServiceBuffer:(CIMSignalServiceBuffer *)signalServiceBuffer receiveSignalPacket:(CIMSignalPacket *)signalPacket {
    if (self.delegate && [self.delegate respondsToSelector:@selector(signalService:receivePacket:)]) {
        [self.delegate signalService:self receivePacket:signalPacket];
    }
}

@end
